package com.pengshun.modules.api.pay.service.impl;

import com.pengshun.modules.aliyun.OosPush;
import com.pengshun.modules.api.coal.repository.MerchantRepository;
import com.pengshun.modules.api.coal.repository.UserRepository;
import com.pengshun.modules.api.coal.util.CommonUtil;
import com.pengshun.modules.api.mapper.OrderMapper;
import com.pengshun.modules.api.mapper.PsUserInComRecordMapper;
import com.pengshun.modules.api.mapper.PsUserInfoMapper;
import com.pengshun.modules.api.order.repository.MerchantOrderRepository;
import com.pengshun.modules.api.order.service.BuyUserOrderService;
import com.pengshun.modules.api.order.service.MerchantOrderService;
import com.pengshun.modules.api.order.service.dto.IncomeRecordDto;
import com.pengshun.modules.api.order.service.dto.MerchantOrderDto;
import com.pengshun.modules.api.order.service.dto.PayResult;
import com.pengshun.modules.api.order.service.mapstruct.IncomeRecordTodo;
import com.pengshun.modules.api.pay.service.*;
import com.pengshun.modules.api.pay.service.dto.*;
import com.pengshun.modules.api.petrol.service.dto.JyPetrolStationEmployeeDto;
import com.pengshun.modules.api.petrol.service.impl.JyPetrolStationOrderServiceImpl;
import com.pengshun.modules.api.petrol.service.repository.JyPetrolStationOrderRepository;
import com.pengshun.modules.api.transport.repository.FreightSettlementRepository;
import com.pengshun.modules.api.transport.repository.SettlementPayRecordRepository;
import com.pengshun.modules.api.transport.repository.TransportTakeCarriageRepository;
import com.pengshun.modules.api.user.repository.IncomeRecordRepository;
import com.pengshun.modules.api.user.repository.IncomeRepository;
import com.pengshun.modules.api.user.repository.OrderPayRecordRepository;
import com.pengshun.modules.common.BaseResult;
import com.pengshun.modules.common.BillType;
import com.pengshun.modules.common.OrderCommon;
import com.pengshun.modules.domain.*;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;


@Service
@RequiredArgsConstructor
public class WechatPayServiceImpl implements WechatPayService {


    private final MerchantOrderRepository merchantOrderRepository;

    private final UserRepository userRepository;

    private final OrderMapper om;

    private final IncomeRecordRepository incomeRecordRepository;

    private final IncomeRecordTodo incomeRecordTodo;

    private final OrderPayRecordRepository orderPayRecordRepository;

    private final FreightSettlementRepository freightSettlementRepository;

    private final SettlementPayRecordRepository settlementPayRecordRepository;

    private final IncomeRepository incomeRepository;

    private final TransportTakeCarriageRepository transportTakeCarriageRepository;

    private final MerchantRepository merchantRepository;

    private final PsUserInComRecordMapper uirm;

    private final JyPetrolStationOrderRepository orderRepository;
    private final PsUserInfoMapper userInfoMapper;

    @Value("${wx.recharge.url}")
    private String notifyUrl;
    @Value("${wx.pay.ip}")
    private String ipAddress;
    @Override
    public BaseResult order(MerchantOrderDto para) {


        return null;
    }

    @Override
    public DorderResult unifiedorder( String body, int totalFee, String attach, String tradeType, String openid) throws Exception {
        String tradeNo = PayUtil.getTradeNo();
        SortedMap<String, String> parm = new TreeMap<>();
        parm.put("attach", attach);
        parm.put("appid", WechatPayDto.appid);
        parm.put("mch_id", WechatPayDto.mch_id);
        parm.put("body", body);
        parm.put("trade_type", tradeType);
        parm.put("nonce_str", PayUtil.getNonceStr());
        parm.put("notify_url", notifyUrl);
        parm.put("out_trade_no", tradeNo);
        parm.put("total_fee", String.valueOf(totalFee));
//        parm.put("spbill_create_ip", getIpAddress(request));
        parm.put("spbill_create_ip", ipAddress);
        parm.put("sign", PayUtil.createSign(parm, WechatPayDto.app_secret));
        String res = XmlUtil.xmlFormat(parm);
        System.err.println(res);
        String retXml = HttpRequest.post(WechatPayDto.unifiedorder, res, false, null, null);
        System.out.println(retXml);
        JaxbUtil resultBinder = new JaxbUtil(Unifiedorder.class, JaxbUtil.CollectionWrapper.class);
        Unifiedorder result = resultBinder.fromXml(retXml);
        if ("FAIL".equals(result.getResultCode()) || "FAIL".equals(result.getReturnCode())) {
            System.err.println("下单失败：" + result.getReturnMsg());
            return null;
        }
        result.setOutTradeNo(tradeNo);
        SortedMap<String, String> pay = new TreeMap<String, String>();
        pay.put("appid", WechatPayDto.appid);
        pay.put("partnerid", WechatPayDto.mch_id);
        pay.put("timestamp", String.valueOf(System.currentTimeMillis()));
        pay.put("noncestr", UUID.randomUUID().toString().replace("-", ""));
        pay.put("prepayid", result.getPrepayId());
        pay.put("package", "Sign=WXPay");
        pay.put("paySign", PayUtil.createSign(pay, WechatPayDto.app_secret));
        pay.put("outTradeNo", result.getOutTradeNo());

        DorderResult unifiedorderResult = new DorderResult(pay.get("appid"), pay.get("partnerid"), pay.get("timestamp"),
                pay.get("noncestr"), pay.get("prepayid"), pay.get("package"), pay.get("paySign"), pay.get("outTradeNo"),null);
        return unifiedorderResult;
    }

    @Override
    public String notifys(HttpServletRequest request) throws Exception {
        try {
            ServletInputStream instream = request.getInputStream();
            StringBuffer sb = new StringBuffer();
            int len;
            byte[] buffer = new byte[1024];
            while ((len = instream.read(buffer)) != -1) {
                sb.append(new String(buffer, 0, len));
            }
            instream.close();
            JaxbUtil resultBinder = new JaxbUtil(PayNotify.class, JaxbUtil.CollectionWrapper.class);
            PayNotify payNotify = resultBinder.fromXml(sb.toString());
            System.err.println("return code-----------:" + payNotify.getReturnCode());
            System.err.println("returnmsg-----------:" + payNotify.getReturnMsg());
            System.err.println("errcode-----------:" + payNotify.getErrCodeDes());
            String res[] = payNotify.getAttach().split("-");
            Long userId = Long.parseLong(res[0]);
            Integer billType = Integer.parseInt(res[1]);
            Long id = Long.parseLong(res[2]);
            String time=payNotify.getTimeEnd();
            SimpleDateFormat format=new SimpleDateFormat("yyyyMMddHHmmss");
            Date timeEnd=format.parse(time);
            WchatPayResult result = new WchatPayResult(payNotify.getTransactionId(),payNotify.getAppid(), payNotify.getMchId(), payNotify.getNonceStr(),
                    payNotify.getSign(), payNotify.getOpenid(), payNotify.getIsSubscribe(), payNotify.getTradeType(),
                    payNotify.getBankType(), payNotify.getTotalFee(), payNotify.getFeeType(),
                    payNotify.getCashFee(), payNotify.getOutTradeNo(), payNotify.getAttach(),
                    timeEnd,  billType,id,userId);
            if (billType.equals(BillType.BILL_TYPE_ONE)) {
                //查询订单支付
                MerchantOrder order = merchantOrderRepository.findById(id).orElseGet(MerchantOrder::new);
                //判断订单状态是否处理过防止重复推送；
                if (order.getOrderStatus().equals(OrderCommon.STATEUS_SIX)) {
                    return PayUtil.notifyResult();
                }
                System.err.println("getAttach---aaaa--------:" + payNotify.getAttach());
                //更新订单状态
                order.setPayWay(OrderCommon.PAY_WAY_TWO);
                order.setOrderStatus(OrderCommon.STATEUS_SIX);
                order.setPayTime(new Date());
                merchantOrderRepository.save(order);
                User user = userRepository.findById(userId).orElseGet(User::new);

                //订单记录表插入数据
                om.saveOrderRecord(id, userId, OrderCommon.STATEUS_SIX, "微信支付", user.getName());
                BigDecimal needPayMoeny=new BigDecimal(result.getTotal_fee()).divide(new BigDecimal(100));
                //订单支付记录表添加数据
                OrderPayRecord payRecord = new OrderPayRecord(order.getOrderId(),  OrderCommon.PAY_WAY_TWO,  needPayMoeny,  user.getId(),new Date());
                orderPayRecordRepository.save(payRecord);
                //账单表添加数据
                Merchant merchant= merchantRepository.findById(order.getMerchantId()).orElseGet(Merchant::new);
                IncomeRecordDto record = new IncomeRecordDto(user.getId(),"PB"+ CommonUtil.getFourRandom(), needPayMoeny,
                        OrderCommon.PAYMENT_TYPE_TWO,OrderCommon.BILL_TYPE_ONE,order.getOrderId(),OrderCommon.PAY_WAY_TWO,
                        "微信支付煤款",1,new Date(),2,merchant.getName(),merchant.getDoorImg(),payRecord.getOrderPayRecordId());
                incomeRecordRepository.save(incomeRecordTodo.toEntity(record));
                //插入支付数据
                om.insertPayWchatResult(result);

                //用户通知
                OosPush.push("付款通知","您的账户微信支出"+needPayMoeny+"元","ALIAS", user.getAlias());
                //商户通知
                User sellUser=userRepository.findById(order.getSellUserId()).orElseGet(User::new);
                OosPush.push("支付通知","您的订单被支付"+needPayMoeny+"元","ALIAS", sellUser.getAlias());

            }
            if (billType.equals(BillType.BILL_TYPE_TWO)) {
                //货运结算
                //查询货运结算
                FreightSettlement settlement=freightSettlementRepository.findById(id).orElseGet(FreightSettlement::new);
                //判断结算状态是否处理过防止重复推送；
                if (settlement.getStatus()==3) {
                    return PayUtil.notifyResult();
                }
                User user=userRepository.findById(settlement.getGatheringUserId()).orElseGet(User::new);
                //更新结算表状态
                settlement.setStatus(3);
                settlement.setCleanDate(new Date());
                freightSettlementRepository.save(settlement);
                //结算支付记录表添加数据
                BigDecimal needPayMoney= new BigDecimal(result.getTotal_fee()).divide(new BigDecimal(100));
                SettlementPayRecord record= settlementPayRecordRepository.save(new SettlementPayRecord(settlement.getFreightSettlementId(),OrderCommon.PAY_WAY_TWO,
                        needPayMoney,userId, new Date()));
                //商户账单表添加数据
                String billNo = settlement.getSettlementNo();
                IncomeRecordDto incomeRecord = new IncomeRecordDto(userId, billNo,needPayMoney,
                        OrderCommon.PAYMENT_TYPE_TWO, OrderCommon.BILL_TYPE_TWO, settlement.getFreightSettlementId(),OrderCommon.PAY_WAY_TWO,
                        "微信结算运费", 1, new Date(),2,user.getName(),user.getAvatarName(),settlement.getTransportTakeCarriageId());
                incomeRecordRepository.save(incomeRecordTodo.toEntity(incomeRecord));
                //插入支付数据
                om.insertPayWchatResult(result);
                //用户账单表添加数据
                Merchant merchant=merchantRepository.findById(settlement.getMerchantId()).orElseGet(Merchant::new);
                IncomeRecordDto userincomeRecord=new IncomeRecordDto(settlement.getGatheringUserId(), billNo,needPayMoney,
                        OrderCommon.BPAYMENT_TYPE_ONE, OrderCommon.BILL_TYPE_FOUR, settlement.getFreightSettlementId(),OrderCommon.PAY_WAY_TWO,
                        "运费收入", 1, new Date(),1,merchant.getName(),merchant.getDoorImg(),settlement.getTransportTakeCarriageId());
                incomeRecordRepository.save(incomeRecordTodo.toEntity(userincomeRecord));
                //更新用户余额
                Income userIncome = incomeRepository.findByUserId(settlement.getGatheringUserId());
                BigDecimal userNowBlanace = userIncome.getUsableBlanace().add(needPayMoney);
                BigDecimal userNowAccountBlanace = userIncome.getAccountBlanace().add(needPayMoney);
                uirm.updateBlanace(userIncome.getUsableBlanace(), userNowBlanace, settlement.getGatheringUserId(),userIncome.getAccountBlanace(),userNowAccountBlanace);

                //更新运单结算状态
                TransportTakeCarriage carriage=transportTakeCarriageRepository.findById(settlement.getTransportTakeCarriageId()).orElseGet(TransportTakeCarriage::new);
                carriage.setCleanStatus(2);
                transportTakeCarriageRepository.save(carriage);

                //商户通知
                User payUser =userRepository.findById(userId).orElseGet(User::new);
                OosPush.push("付款通知","您的账户微信支出"+needPayMoney+"元","ALIAS", payUser.getAlias());
                //用户通知
                OosPush.push("到账通知","您的账户收入"+needPayMoney+"元","ALIAS", user.getAlias());
            }
            if (billType.equals(BillType.BILL_TYPE_THREE)) {
                //煤款收入
            }
            if (billType.equals(BillType.BILL_TYPE_FOUR)) {
                //运费收入
            }
            if (billType.equals(BillType.BILL_TYPE_FIVE)) {
                //充值
                //插入支付数据
                om.insertPayWchatResult(result);
                //用户账单表添加数据
                BigDecimal payMoney=new BigDecimal(result.getTotal_fee()).divide(new BigDecimal(100));
                IncomeRecordDto userincomeRecord=new IncomeRecordDto(userId, "PB"+CommonUtil.getFourRandom(),payMoney,
                        OrderCommon.BPAYMENT_TYPE_ONE, OrderCommon.BILL_TYPE_FIVE, userId,OrderCommon.PAY_WAY_TWO, "微信余额充值", 1, new Date(),1,"微信","https://binmeitong.oss-cn-beijing.aliyuncs.com/coal/202103241806062456",null);
                incomeRecordRepository.save(incomeRecordTodo.toEntity(userincomeRecord));
                //更新用户余额
                Income userIncome = incomeRepository.findByUserId(userId);
                BigDecimal userNowBlanace = userIncome.getUsableBlanace().add(payMoney);
                BigDecimal userNowAccountBlanace = userIncome.getAccountBlanace().add(payMoney);

                uirm.updateBlanace(userIncome.getUsableBlanace(), userNowBlanace, userId,userIncome.getAccountBlanace(),userNowAccountBlanace);

            }
            if (billType.equals(BillType.BILL_TYPE_SIX)) {
                //提现
            }
            if (equals(BillType.BILL_TYPE_SEVEN)) {
                //退款
            }
            if (billType.equals(BillType.BILL_TYPE_EIGHT)) {
                //其他
            }
            if (billType.equals(BillType.BILL_TYPE_NINE)) {
                //加油支付
                JyPetrolStationOrder order=orderRepository.findById(id).orElseGet(JyPetrolStationOrder::new);
                //判断结算状态是否处理过防止重复推送；
                if (order.getPayStatus()==2) {
                    return PayUtil.notifyResult();
                }
                //插入支付数据
                om.insertPayWchatResult(result);
                //修改订单状态
                order.setPayStatus(2);
                orderRepository.save(order);
                //更新商户账户余额
                BigDecimal needPayMoney = order.getRealAmount();
                List<JyPetrolStationEmployeeDto> list = userInfoMapper.findByPetrolStationId(order.getPetrolStationId());
                JyPetrolStationEmployeeDto admin = new JyPetrolStationEmployeeDto();
                for (JyPetrolStationEmployeeDto user : list) {
                    if ("管理员".equals(user.getRole())) {
                        admin = user;
                    }
                    //商户通知
                    OosPush.push("到账通知", "您的账户收入油款" + needPayMoney + "元", "ALIAS", user.getAlias());
                }
                Income merchantUser = incomeRepository.findByUserId(admin.getUserId());
                Long merUserId = merchantUser.getUserId();

                BigDecimal nowBlanace = merchantUser.getUsableBlanace().add(needPayMoney);
                BigDecimal userNowAccountBlanace = merchantUser.getAccountBlanace().add(needPayMoney);
                uirm.updateBlanace(merchantUser.getUsableBlanace(), nowBlanace, merUserId, merchantUser.getAccountBlanace(), userNowAccountBlanace);
                //商户账单表添加数据
                User users = userRepository.findById(order.getBuyUserId()).orElseGet(User::new);
                IncomeRecordDto incomeRecord = new IncomeRecordDto(merUserId, order.getSettNo(), needPayMoney, OrderCommon.BPAYMENT_TYPE_ONE, BillType.BILL_TYPE_TEN, order.getPetrolStationOrderId(),
                        OrderCommon.PAY_WAY_TWO, "加油收入", 1, new Date(), 1, users.getName(), users.getAvatarName(), null);
                incomeRecordRepository.save(incomeRecordTodo.toEntity(incomeRecord));
                //用户账单表加数据
                IncomeRecordDto userIncomeRecord = new IncomeRecordDto(users.getId(),  order.getSettNo(), needPayMoney, OrderCommon.PAYMENT_TYPE_TWO, BillType.BILL_TYPE_NINE, order.getPetrolStationOrderId(),
                        OrderCommon.PAY_WAY_ONE, "加油支付", 1, new Date(), 1, admin.getName(), admin.getLogo(), null);
                incomeRecordRepository.save(incomeRecordTodo.toEntity(userIncomeRecord));
            }
        } catch (DuplicateKeyException e) {
            return PayUtil.notifyResult();
        }
        return PayUtil.notifyResult();
    }

    @Override
    public BaseResult orderQuery(String outTradeNo) {
//        SortedMap<String, String> parm = new TreeMap<>();
//        parm.put("appid", WechatPayDto.appid);
//        parm.put("mch_id", WechatPayDto.mch_id);
//        parm.put("out_trade_no", outTradeNo);
//        parm.put("nonce_str", PayUtil.getNonceStr());
//        parm.put("sign", PayUtil.createSign(parm, WechatPayDto.app_secret));
//        String retXml = HttpRequest.post(WechatPayDto.ORDERQUERY, XmlUtil.xmlFormat(parm), false, null, null);
//        JaxbUtil resultBinder = new JaxbUtil(OrderQuery.class, JaxbUtil.CollectionWrapper.class);
//        OrderQuery orderQuery = resultBinder.fromXml(retXml);
//
//        if ("SUCCESS".equals(orderQuery.getReturnCode())) {
//            return  new BaseResult(0);
//        }else{
//            return  new BaseResult(1,orderQuery.getErrCodeDes());
//        }
        WchatPayResult result = om.selectpayMoney(outTradeNo);
        if (result != null) {
            PayResult res=new PayResult(new BigDecimal(result.getTotal_fee()).divide(new BigDecimal(100)));
            return new BaseResult(0, res);
        } else {
            return new BaseResult(1, "未支付");
        }
    }

    public final static String getIpAddress(HttpServletRequest request) {
        // 获取请求主机IP地址,如果通过代理进来，则透过防火墙获取真实IP地址

        String ip = request.getHeader("X-Forwarded-For");

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
        } else if (ip.length() > 15) {
            String[] ips = ip.split(",");
            for (int index = 0; index < ips.length; index++) {
                String strIp = (String) ips[index];
                if (!("unknown".equalsIgnoreCase(strIp))) {
                    ip = strIp;
                    break;
                }
            }
        }
        return ip;
    }

}
